/* * @(#)DNDHelper.java * * Project: JHotdraw - a GUI framework for technical drawings * http://www.jhotdraw.org * http://jhotdraw.sourceforge.net * Copyright: (c) by the original author(s) and all contributors * License: Lesser GNU Public License (LGPL) * http://www.opensource.org/licenses/lgpl-license.html */ package org.jhotdraw.contrib.dnd; import org.jhotdraw.framework.*; import java.awt.Component; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.datatransfer.Transferable; import java.awt.dnd.*; import java.io.*; import java.util.List; /** * Changes made in hopes of eventually cleaning up the functionality and * distributing it sensibly. 1/10/02 * @author C.L.Gilbert <dnoyeb@users.sourceforge.net> * @version <$CURRENT_VERSION$> */ public abstract class DNDHelper { public static DataFlavor ASCIIFlavor = new DataFlavor("text/plain; charset=ascii", "ASCII text"); private DragGestureRecognizer dgr; private DragGestureListener dragGestureListener; private DropTarget dropTarget; private DragSourceListener dragSourceListener; private DropTargetListener dropTargetListener; private boolean isDragSource = false; private boolean isDropTarget = false; public DNDHelper(boolean newIsDragSource, boolean newIsDropTarget){ isDragSource = newIsDragSource; isDropTarget = newIsDropTarget; } /** * Do not call this from the constructor. its methods are overridable. */ public void initialize(DragGestureListener dgl) { if (isDragSource) { setDragGestureListener(dgl); setDragSourceListener(createDragSourceListener()); setDragGestureRecognizer(createDragGestureRecognizer(getDragGestureListener())); } if (isDropTarget) { setDropTargetListener(createDropTargetListener()); setDropTarget(createDropTarget()); } } public void deinitialize(){ if (getDragSourceListener() != null) { destroyDragGestreRecognizer(); setDragSourceListener(null); } if (getDropTargetListener() != null) { setDropTarget(null); setDropTargetListener(null); } } // public void setDragSourceState(boolean state) { // if(state == false){ // getDragGestureRecognizer().setSourceActions(DnDConstants.ACTION_NONE); // } // else { // getDragGestureRecognizer().setSourceActions(getDragSourceActions()); // } // } protected abstract DrawingView view(); protected abstract DrawingEditor editor(); protected static Object processReceivedData(DataFlavor flavor, Transferable transferable) { Object receivedData = null; if (transferable == null) { return null; } try { if (flavor.equals(DataFlavor.stringFlavor)) { receivedData = transferable.getTransferData(DataFlavor.stringFlavor); } else if (flavor.equals(DataFlavor.javaFileListFlavor)) { List aList = (List)transferable.getTransferData(DataFlavor.javaFileListFlavor); File fList [] = new File[aList.size()]; aList.toArray(fList); receivedData = fList; } else if (flavor.equals(ASCIIFlavor)) { /* this may be too much work for locally received data */ InputStream is = (InputStream)transferable.getTransferData(ASCIIFlavor); int length = is.available(); byte[] bytes = new byte[length]; int n = is.read(bytes); if (n > 0) { /* seems to be a 0 tacked on the end of Windows strings. I * havent checked other platforms. This does not happen * with windows socket io. strange? */ //for (int i = 0; i < length; i++) { // if (bytes[i] == 0) { // length = i; // break; // } //} receivedData = new String(bytes, 0, n); } } else if (flavor.equals(DNDFiguresTransferable.DNDFiguresFlavor)) { receivedData = transferable.getTransferData(DNDFiguresTransferable.DNDFiguresFlavor); } } catch (java.io.IOException ioe) { System.err.println(ioe); } catch (UnsupportedFlavorException ufe) { System.err.println(ufe); } catch (ClassCastException cce) { System.err.println(cce); } return receivedData; } /** * This must reflect the capabilities of the dragSsource, not your desired * actions. If you desire limited drag actions, then I suppose you need to * make a new drag gesture recognizer? I do know that if you put for instance * ACTION_COPY but your device supports ACTION_COPY_OR_MOVE, then the receiving * target may show the rejected icon, but will still be forced improperly to * accept your MOVE since the system is not properly calling your MOVE a MOVE * because you claimed incorrectly that you were incapable of MOVE. */ protected int getDragSourceActions() { return DnDConstants.ACTION_COPY_OR_MOVE; } protected int getDropTargetActions(){ return DnDConstants.ACTION_COPY_OR_MOVE; } protected void setDragGestureListener(DragGestureListener dragGestureListener){ this.dragGestureListener = dragGestureListener; } protected DragGestureListener getDragGestureListener(){ return dragGestureListener; } protected void setDragGestureRecognizer(DragGestureRecognizer dragGestureRecognizer){ dgr = dragGestureRecognizer; } protected DragGestureRecognizer getDragGestureRecognizer(){ return dgr; } protected void setDropTarget(DropTarget newDropTarget){ if ((newDropTarget == null) && (dropTarget != null)) { dropTarget.setComponent(null); dropTarget.removeDropTargetListener(getDropTargetListener()); } dropTarget = newDropTarget; } protected DropTarget createDropTarget() { DropTarget dt = null; if (Component.class.isInstance(view())) { try { dt = new DropTarget((Component)view(), getDropTargetActions(), getDropTargetListener()); //System.out.println(view().toString() + " Initialized to DND."); } catch (NullPointerException npe) { System.err.println("View Failed to initialize to DND."); System.err.println("Container likely did not have peer before the DropTarget was added"); System.err.println(npe); npe.printStackTrace(); } } return dt; } /** * Used to create the gesture recognizer which in effect turns on draggability. */ protected DragGestureRecognizer createDragGestureRecognizer(DragGestureListener dgl) { DragGestureRecognizer aDgr = null; if (Component.class.isInstance(view())) { Component c = (Component)view(); aDgr = java.awt.dnd.DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer( c, getDragSourceActions(), dgl); //System.out.println("DragGestureRecognizer created: " + view()); } return aDgr; } /** * Used to destroy the gesture listener which ineffect turns off dragability. */ protected void destroyDragGestreRecognizer() { //System.out.println("Destroying DGR " + view()); if (getDragGestureRecognizer() != null) { getDragGestureRecognizer().removeDragGestureListener(getDragGestureListener()); getDragGestureRecognizer().setComponent(null); setDragGestureRecognizer(null); } } protected void setDropTargetListener(DropTargetListener dropTargetListener){ this.dropTargetListener = dropTargetListener; } protected DropTargetListener getDropTargetListener(){ return dropTargetListener; } protected DropTargetListener createDropTargetListener(){ return new JHDDropTargetListener(editor(),view()); } public DragSourceListener getDragSourceListener(){ return dragSourceListener; } protected void setDragSourceListener(DragSourceListener dragSourceListener){ this.dragSourceListener = dragSourceListener; } protected DragSourceListener createDragSourceListener(){ return new JHDDragSourceListener(editor(),view()); } } /** * These transferable objects are used to package your data when you want * to initiate a transfer. They are not used when you only want to receive * data. Formating the data is the responsibility of the sender primarily. * Untested. Used for dragging ASCII text out of JHotDraw */ /* public class ASCIIText implements Transferable { String s = new String("This is ASCII text"); byte[] bytes; public DataFlavor[] getTransferDataFlavors() { return new DataFlavor[] { ASCIIFlavor }; } public boolean isDataFlavorSupported(DataFlavor dataFlavor) { return dataFlavor.equals(ASCIIFlavor); } public Object getTransferData(DataFlavor dataFlavor) throws UnsupportedFlavorException, IOException { if (!isDataFlavorSupported(dataFlavor)) throw new UnsupportedFlavorException(dataFlavor); bytes = new byte[s.length() + 1]; for (int i = 0; i < s.length(); i++) bytes = s.getBytes(); bytes[s.length()] = 0; return new ByteArrayInputStream(bytes); } }*/